package DataModel;

import java.util.ArrayList;

import Interfaces.SortableElements;

/**
 * This class represents a bucket where {@link Feature}s are stored in.<br>
 * {@link Feature}s of the same genomic feauture can differ in their type and
 * are stored together into this {@link FeatureBucket}
 * 
 * @author Stefan Lorenz <br>
 *         <b>Date:</b> 12.11.2012
 */
public class FeatureBucket implements SortableElements {

    
    /**
     * List where all {@link Feature}s are stored in
     */
    private ArrayList<Feature> featureList;
    /**
     * The name of the {@link FeatureBucket}
     */
    private String name;
    
    /**
     * Start position of the bucket which is the most left position of the {@link Feature}s in this bucket
     */
    private int start;
    /**
     * Stop position of the bucket which is the most right position of the {@link Feature}s in this bucket
     */
    private int stop;
    
    /**
     * The strand of the bucket which can be '+' or '-'
     */
    private String strand;

    /**
     * Constructor of an empty bucket
     */
    public FeatureBucket() {
	this.featureList = new ArrayList<Feature>();
	this.name = "";
	this.start = -1;
	this.stop = -1;
	this.strand = "";
    }

    /**
     * Constructor of an bucket filled with the given {@link Feature}.<br>
     * Further information are set from this feature
     * @param feature Feature filled into the new created bucket
     */
    public FeatureBucket(Feature feature) {
	this.featureList = new ArrayList<Feature>();
	this.featureList.add(feature);
	this.name = feature.getName();
	this.start = feature.getStart();
	this.stop = feature.getStop();
	this.strand = feature.getStrand();
    }


    /* (non-Javadoc)
     * @see Interfaces.SortableElements#getStart()
     */
    public int getStart() {
	return this.start;
    }

    /* (non-Javadoc)
     * @see Interfaces.SortableElements#getStop()
     */
    public int getStop() {
	return this.stop;
    }

    /**
     * Adds a feature only if it is the right bucket name and the strand must be equal it returns <code>true</code>.<br>
     * Otherwise the feature will not be added to the bucket and  return value is <code>false</code> 
     * 
     * @param f the feature to add into a this bucket
     * @return <code>false</code> or <code>true</code> 
     */
    public boolean addNewComponent(Feature f) {
	if (this.featureList.size() == 0) {
	    this.featureList.add(f);
	    this.name = f.getName();
	    this.start = f.getStart();
	    this.stop = f.getStop();
	    this.strand = f.getStrand();
	    return true;
	} else if (this.name.equals(f.getName()) && this.strand.equals(f.getStrand())) {
	    this.featureList.add(f);
	    if (f.getStart() < this.start)
		this.start = f.getStart();
	    if (f.getStop() > this.stop)
		this.stop = f.getStop();
	    return true;
	} else {
	    return false;
	}
    }

    /**
     * Adds a feature to the end of the bucket
     * @param f Feature to add
     */
    public void addFeature(Feature f) {
	this.featureList.add(f);
    }

    /**
     * Adds a feature to the bucket to a given position 
     * @param index Position in the bucket where to add 
     * @param f Feature to add
     */
    public void addFeature(int index, Feature f) {
	this.featureList.add(index, f);
    }

    /**
     * Sets a given feature list
     * @param featureList List of features to set
     */
    public void setFeaturesOfBucket(ArrayList<Feature> featureList) {
	this.featureList = featureList;
    }

    /**
     * Returns a list with all features of the bucket
     * @return list of features of teh bucket
     */
    public ArrayList<Feature> getFeaturesOfBucket() {
	return this.featureList;
    }


    /**
     * Sets the name of the bucket
     * @param name Name of the bucket
     */
    public void setName(String name) {
	this.name = name;
    }

    /**
     * Returns the name of the bucket
     * @return Name of the bucket
     */
    public String getName() {
	return name;
    }

    /**
     * Sets the strand of the bucket which is either '+' or '-'
     * @param strand Strand of the bucket
     */
    public void setStrand(String strand) {
	this.strand = strand;
    }

    /**
     * Returns the strand of the bucket which is either '+' or '-'
     * @return Strand of the bucket
     */
    public String getStrand() {
	return strand;
    }

    /**
     * Sets the start position of the bucket
     * @param start Start position of the bucket
     */
    public void setStart(int start) {
	this.start = start;
    }

    /**
     * Sets the stop position of the bucket
     * @param stop Stop position of the bucket
     */
    public void setStop(int stop) {
	this.stop = stop;
    }

    /**
     * Refreshes the bucket positions out of all positions given by the added features
     */
    public void refreshBucketPositions() {
	int min = -1;
	int max = -1;
	for (int i = 0; i < this.featureList.size(); i++) {
	    for (int j = 0; j < this.featureList.get(i).getListOfPositions().size(); j++) {
		if (i == 0 && j == 0) {
		    min = this.featureList.get(i).getListOfPositions().get(j).getStart();
		    max = this.featureList.get(i).getListOfPositions().get(j).getStop();
		} else {
		    if (this.featureList.get(i).getListOfPositions().get(j).getStart() < min)
			min = this.featureList.get(i).getListOfPositions().get(j).getStart();
		    if (this.featureList.get(i).getListOfPositions().get(j).getStop() > max)
			max = this.featureList.get(i).getListOfPositions().get(j).getStop();
		}
	    }
	}
	this.start = min;
	this.stop = max;
    }
}
